package com.jiangyg.mall.admin.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jiangyg.mall.admin.constant.ColumnConstant;
import com.jiangyg.mall.admin.dao.PermissionDao;
import com.jiangyg.mall.admin.dao.RoleDao;
import com.jiangyg.mall.admin.dao.RoleUserDao;
import com.jiangyg.mall.admin.dto.RoleDTO;
import com.jiangyg.mall.admin.entity.Permission;
import com.jiangyg.mall.admin.entity.Role;
import com.jiangyg.mall.admin.entity.RoleUser;
import com.jiangyg.mall.admin.enums.PermissionType;
import com.jiangyg.mall.admin.vo.RoleVO;
import com.jiangyg.mall.authz.UserInfoHolder;
import com.jiangyg.mall.core.enums.Enable;
import com.jiangyg.mall.core.exception.BusinessException;
import com.jiangyg.mall.core.utils.I18n;
import com.jiangyg.mall.core.utils.bean.BeanUtils;
import com.jiangyg.mall.db.mybatis.BaseServiceImpl;
import com.jiangyg.mall.db.mybatis.metadata.Pager;
import com.jiangyg.mall.core.support.restful.Pagination;
import org.apache.commons.collections.CollectionUtils;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class RoleServiceImpl extends BaseServiceImpl<RoleDao, Role> implements RoleService {

    private final RoleUserDao roleUserDao;

    private final PermissionDao permissionDao;

    @Autowired
    public RoleServiceImpl(RoleDao roleDao, RoleUserDao roleUserDao, PermissionDao permissionDao) {
        super(roleDao);
        this.roleUserDao = roleUserDao;
        this.permissionDao = permissionDao;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public Pagination<RoleVO> selectPagination(Pagination<RoleVO> pagination, Long userId) throws Exception {
        // 1. 构建查询条件
        final QueryWrapper<Role> wrapper = this.buildQueryWrapper(pagination, Role.class);
        // 2. 如果非超级管理员则查询用户已有的角色
        if (!UserInfoHolder.isAdmin(userId)) {
            final QueryWrapper<RoleUser> ruwrapper = new QueryWrapper<>();
            ruwrapper.eq(ColumnConstant.USER_ID, userId);
            final List<RoleUser> roleUsers = this.roleUserDao.selectList(ruwrapper);
            // 2.1 如果普通用户没有授权角色则直接返回
            if (CollectionUtils.isEmpty(roleUsers)) {
                pagination.setTotal(0);
                pagination.setRecords(Collections.emptyList());
                return pagination;
            }
            // 2.2 追加普通用户角色列表条件
            final List<Long> roleIds = roleUsers.stream().map(RoleUser::getRoleId).collect(Collectors.toList());
            wrapper.in(ColumnConstant.ID, roleIds);
        }
        // 3. 分页查询
        Pager<Role> pager = Pager.from(pagination);
        pager = this.baseMapper.selectPage(pager, wrapper);
        return pager.toPagination(RoleVO.class);
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<RoleVO> selectRoleList(Long userId) throws Exception {
        final QueryWrapper<Role> wrapper = new QueryWrapper<>();
        // 如果非超级管理员则查询用户已有的角色
        if (!UserInfoHolder.isAdmin(userId)) {
            final QueryWrapper<RoleUser> ruwrapper = new QueryWrapper<>();
            ruwrapper.eq(ColumnConstant.USER_ID, userId);
            final List<RoleUser> roleUsers = this.roleUserDao.selectList(ruwrapper);
            // 如果普通用户没有授权角色则直接返回
            if (CollectionUtils.isEmpty(roleUsers)) {
                return Collections.emptyList();
            }
            // 追加普通用户角色列表条件
            final List<Long> roleIds = roleUsers.stream().map(RoleUser::getRoleId).collect(Collectors.toList());
            wrapper.in(ColumnConstant.ID, roleIds);
        }
        final List<Role> roles = this.baseMapper.selectList(wrapper);
        return BeanUtils.transformList(roles, RoleVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveOrUpdate(RoleDTO dto, Long userId) throws Exception {
        // 判断是否有修改权限：1、超级管理员可以任意修改  2、角色创建者可以修改
        Role role;
        if (dto.getId() != null) {
            role = this.baseMapper.selectById(dto.getId());
            if (role != null
                    && !UserInfoHolder.isAdmin(userId)
                    && !userId.equals(role.getCreateUserId())) {
                throw new BusinessException(I18n.getString("mall.admin.role.update.havePermission"));
            }
            // 验证通过，执行修改
            if (role != null) {
                BeanUtils.copyProperties(role, dto);
                return this.baseMapper.updateById(role) > 0;
            }
        }
        role = new Role();
        BeanUtils.copyProperties(role, dto);
        return this.baseMapper.insert(role) > 0;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public RoleVO selectById(Long roleId) throws Exception {
        return this.executeSelectById(roleId, RoleVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(List<Long> roleIds) {
        // 判断角色下是否有用户
        final QueryWrapper<RoleUser> wrapper = new QueryWrapper<>();
        wrapper.in(ColumnConstant.ROLE_ID, roleIds);
        wrapper.eq(ColumnConstant.ENABLE, Enable.Y.scode);
        final Integer count = roleUserDao.selectCount(wrapper);
        if (count > 0) {
            throw new BusinessException(I18n.getString("mall.admin.role.delete.haveUser"));
        }
        // 判断角色下是否存在资源
        final QueryWrapper<Permission> pwrapper = new QueryWrapper<>();
        pwrapper.in(ColumnConstant.REFERENCE_ID, roleIds);
        pwrapper.eq(ColumnConstant.TYPE, PermissionType.R.code);
        pwrapper.eq(ColumnConstant.ENABLE, Enable.Y.scode);
        final Integer pcount = permissionDao.selectCount(pwrapper);
        if (pcount > 0) {
            throw new BusinessException(I18n.getString("mall.admin.role.delete.havePermission"));
        }
        return this.baseMapper.deleteBatchIds(roleIds) > 0;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<String> selectResourcesById(Long roleId) {
        return this.permissionDao.selectResourceIdsByReferenceId(roleId);
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public boolean haveUpdatePermission(Long roleId, Long userId) {
        // 判断是否超管
        if (UserInfoHolder.isAdmin(userId)) {
            return true;
        }
        // 判断角色是否登录用户创建
        final QueryWrapper<RoleUser> wrapper = new QueryWrapper<>();
        wrapper.eq(ColumnConstant.ROLE_ID, roleId);
        wrapper.eq(ColumnConstant.CREATE_USER_ID, userId);
        wrapper.eq(ColumnConstant.ENABLE, Enable.Y.scode);
        final Integer count = roleUserDao.selectCount(wrapper);
        return count > 0;
    }

}
